using System;
using System.Collections.Generic;
using CoverageRunner;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.IO;

namespace Insane.MSBuildTasks
{
    public class VstsCoverageRunner : Task
    {
        public override bool Execute()
        {
            List<string> targets = new List<string>();
            foreach (ITaskItem item in targetsToInstrument)
                targets.Add(item.ItemSpec);

            VisualStudioInstrumentation instrumentation = new VisualStudioInstrumentation(vsinstrPath);
            instrumentation.Instrument(outputPathForInstrumentedAssemblies, targets);

            if (string.IsNullOrEmpty(symbolsPath)) symbolsPath = outputPathForInstrumentedAssemblies;
            if (string.IsNullOrEmpty(exePath)) exePath = outputPathForInstrumentedAssemblies;

            UnitTestRunner testRunner = new UnitTestRunner(unitTestRunnerExecutable, unitTestArguments);
            CoverageReportCreator reportCreator = new CoverageReportCreator(vstsCoverageOutputFile, symbolsPath, exePath, outputXml, coverageStylesheet, htmlOutputFile);
            CoverageGenerator coverageGenerator = new CoverageGenerator(vstsCoverageOutputFile, testRunner, reportCreator);

            coverageGenerator.Execute();
            
            return true;
        }


        /// <summary>
        /// Location of VSINSTR.EXE on the build machine. This is an included program with versions of Visual Studio containing
        /// the testing tools (Development and Test editions for VS2008)
        /// </summary>
        public string VsinstrPath
        {
            get { return vsinstrPath; }
            set { vsinstrPath = value; }
        }
        private string vsinstrPath = @"C:\Program Files\Microsoft Visual Studio 9.0\Team Tools\Performance Tools";


        /// <summary>
        /// Assemblies to instrument, including path information e.g. "E:\devtest\ClassLibrary1.dll"
        /// </summary>
        [Required]
        public ITaskItem[] TargetsToInstrument
        {
            get { return targetsToInstrument; }
            set { targetsToInstrument = value; }
        }
        private ITaskItem[] targetsToInstrument;

        /// <summary>
        /// The location of the test runner (nunit.console.exe or mbunit.cons.exe for example)
        /// </summary>
        [Required]
        public string UnitTestRunnerExecutable
        {
            get { return unitTestRunnerExecutable; }
            set { unitTestRunnerExecutable = value; }
        }
        private string unitTestRunnerExecutable;

        /// <summary>
        /// Arguments to pass to test executable. All assemblies here should point to the ones in
        /// the instrumentation directory, not the originals they were instrumented from
        /// </summary>
        [Required]
        public string UnitTestArguments
        {
            get { return unitTestArguments; }
            set { unitTestArguments = value; }
        }
        private string unitTestArguments;

        /// <summary>
        /// Location to output instrumented assemblies to. VSINSTR will create an instrumented version of each target assembly
        /// and put it into this location. Coverage is then run against these assemblies. 
        /// Setting this to the same location as the original assemblies will result in them being overwritten with instrumented versions.
        /// </summary>
        [Required]
        public string OutputPathForInstrumentedAssemblies
        {
            get { return outputPathForInstrumentedAssemblies; }
            set { outputPathForInstrumentedAssemblies = value; }
        }
        private string outputPathForInstrumentedAssemblies = @"c:\instrumentation";

        /// <summary>
        /// Required for the VisualStudio CoverageInfoManager class. Optional, will default to the OutputPathForInstrumentationData
        /// </summary>
        public string SymbolsPath
        {
            get { return symbolsPath; }
            set { symbolsPath = value; }
        }
        private string symbolsPath;

        /// <summary>
        /// Required for the VisualStudio CoverageInfoManager class. Optional, will default to the OutputPathForInstrumentationData
        /// </summary>
        public string ExePath
        {
            get { return exePath; }
            set { exePath = value; }
        }
        private string exePath;

        /// <summary>
        /// The file to write coverage output to. This is normally something like "c:\mytests.coverage", and should include path information.
        /// </summary>
        [Required]
        public string VstsCoverageOutputFile
        {
            get { return vstsCoverageOutputFile; }
            set { vstsCoverageOutputFile = value; }
        }
        private string vstsCoverageOutputFile = @"coveragedata.coverage";

        /// <summary>
        /// The XML file to write the .coverage (from VstsCoverageOutputFile) into.
        /// This is normally something like "c:\mytests.xml", and should include path information.
        /// </summary>
        /// <remarks>
        /// VisualStudio can load either the .coverage file or the .xml file into the IDE, but
        /// to convert the coverage data into a display format we need it in XML first.
        /// </remarks>
        [Required]
        public string OutputXml
        {
            get { return outputXml; }
            set { outputXml = value; }
        }
        private string outputXml = @"coveragedata.xml";

        /// <summary>
        /// The XSLT file to use to transform the XML output into a readable report.
        /// This is normally something like "c:\coverage.xslt"
        /// </summary>
        [Required]
        public string CoverageStylesheet
        {
            get { return coverageStylesheet; }
            set { coverageStylesheet = value; }
        }
        private string coverageStylesheet = @"coverage.xslt";

        /// <summary>
        /// The output file for the results of the XML + XSLT transformation.
        /// This is normally something like "c:\myreport.html"
        /// </summary>
        [Required]
        public string HtmlOutputFile
        {
            get { return htmlOutputFile; }
            set { htmlOutputFile = value; }
        }
        private string htmlOutputFile = @"coveragereport.html";

    }
}